home *** CD-ROM | disk | FTP | other *** search
/ NASA Climatology Interdisciplinary Data Collection / NASA Climatology Interdisciplinary Data Collection - Disc 4.iso / software / grads / doc / doty / gxchpl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-23  |  6.8 KB  |  294 lines

  1. /* Copyright (c) 1994 by Brian Doty
  2.    See file COPYRIGHT for complete rights and liability information. */
  3.  
  4. /* Plot character strings using the Hershey fonts */
  5.  
  6. #include <stdio.h>
  7. #include <math.h>
  8. #include <malloc.h>
  9. #include "gx.h"
  10.  
  11. static char *fch[10];   /* Pointers to font data once it is read in */
  12. static int *foff[10];   /* Pointers to character offsets */
  13. static int *flen[10];   /* Pointers to character lengths */
  14. static int dfont;       /* Default font */
  15.  
  16. /* Initialize */
  17.  
  18. void gxchii (void) {
  19. int i;
  20.   for (i=0; i<10; i++) fch[i] = NULL;
  21.   dfont = 0;
  22. }
  23.  
  24. /* Change default font */
  25.  
  26. void gxchdf (int df) {
  27.   if (df<0 || df>9) return;
  28.   dfont = df;
  29. }
  30.  
  31. /* Plot character string */
  32.  
  33. void gxchpl (char *chrs, int len, float x, float y, float height,
  34.              float width, float angle) {
  35. int i,j,fn,ic,jc,cnt,ipen,supsub;
  36. float xc,yc,xscl,yscl,xs,ys,w,d,ang,rx,ry,yoff;
  37. char *cdat;
  38.  
  39.   xscl = width/21.0;
  40.   yscl = height/22.0;
  41.   fn = dfont;
  42.   angle = angle * 3.1416/180.0;
  43.   supsub = 0;
  44.   while (*chrs!='\0' && len>0) {
  45.     while (*chrs=='`') {
  46.       if (*(chrs+1)>='0' && *(chrs+1)<='9') {
  47.         fn = (int)*(chrs+1) - 48;
  48.         chrs+=2;
  49.         len-=2;
  50.       } else if (*(chrs+1)=='a') {
  51.         supsub = 1;
  52.         chrs+=2; len-=2;
  53.       } else if (*(chrs+1)=='b') {
  54.         supsub = 2;
  55.         chrs+=2; len-=2;
  56.       } else if (*(chrs+1)=='n') {
  57.         supsub = 0;
  58.         chrs+=2; len-=2;
  59.       } else break;
  60.     }
  61.     if (*chrs!='\0' && len>0) {
  62.       if (angle==0.0) {           /* Fast path for ang=0 */
  63.         cdat = gxchgc ( (int)*(chrs), fn, &cnt);
  64.         if (cdat==NULL) return;
  65.         ic = (int)(*(cdat+3)) - 82;
  66.         jc = (int)(*(cdat+4)) - 82;
  67.         if (supsub) {
  68.           xs = xscl*0.45; ys = yscl*0.45;
  69.           if (supsub==1) yoff = height*0.35;
  70.           else yoff = -1.0*height*0.42;
  71.         } else {
  72.           xs = xscl; ys = yscl; yoff = 0.0;
  73.         }
  74.         w = (float)(jc-ic) * xs * 1.05;
  75.         xc= x + w/2.0;
  76.         yc = y + height*0.42 + yoff;
  77.         cdat += 5;
  78.         ipen = 3;
  79.         for (i=1; i<cnt; i++) {
  80.           ic = (int)*cdat;
  81.           jc = (int)*(cdat+1);
  82.           if (ic==32) ipen = 3;
  83.           else {
  84.             ic = ic - 82;
  85.             jc = jc - 82;
  86.             rx = xc + ((float)ic)*xs;
  87.             ry = yc - ((float)jc)*ys;
  88.             if (ipen==3) gxmove (rx,ry);
  89.             else gxdraw (rx,ry);
  90.             ipen = 2;
  91.           }
  92.           cdat += 2;
  93.         }
  94.         x = x + w;
  95.         chrs++; len--;
  96.       } else {
  97.         cdat = gxchgc ( (int)*(chrs), fn, &cnt);
  98.         if (cdat==NULL) return;
  99.         ic = (int)(*(cdat+3)) - 82;
  100.         jc = (int)(*(cdat+4)) - 82;
  101.         if (supsub) {
  102.           xs = xscl*0.45; ys = yscl*0.45;
  103.           if (supsub==1) yoff = height*0.35;
  104.           else yoff = -1.0*height*0.42;
  105.         } else {
  106.           xs = xscl; ys = yscl; yoff = 0.0;
  107.         }
  108.         w = (float)(jc-ic) * xs * 1.05;
  109.         d = hypot(w/2.0,height*0.42+yoff);
  110.         ang = atan2(height*0.42+yoff,w/2.0)+angle;
  111.         xc = x + d*cos(ang);
  112.         yc = y + d*sin(ang);
  113.         cdat += 5;
  114.         ipen = 3;
  115.         for (i=1; i<cnt; i++) {
  116.           ic = (int)*cdat;
  117.           jc = (int)*(cdat+1);
  118.           if (ic==32) ipen = 3;
  119.           else {
  120.             ic = ic - 82;
  121.             jc = jc - 82;
  122.             rx = ((float)ic)*xs;
  123.             ry = -1.0*((float)jc)*ys;
  124.             if (rx==0.0 && ry==0.0) {
  125.               d = 0.0; ang = 0.0;
  126.             } else {
  127.               d = hypot(rx,ry);
  128.               ang = atan2(ry,rx)+angle;
  129.             }
  130.             rx = xc + d*cos(ang);
  131.             ry = yc + d*sin(ang);
  132.             if (ipen==3) gxmove (rx,ry);
  133.             else gxdraw (rx,ry);
  134.             ipen = 2;
  135.           }
  136.           cdat += 2;
  137.         }
  138.         x = x + w*cos(angle);
  139.         y = y + w*sin(angle);
  140.         chrs++; len--;
  141.       }
  142.     }
  143.   }
  144. }
  145.  
  146. /* Figure out the length of a character string, without
  147.    plotting it */
  148.  
  149. int gxchln (char *chrs, int len, float width, float *w) {
  150. int fn,ic,jc,supsub;
  151. float xscl,xs;
  152. char *cdat;
  153.  
  154.   *w = 0.0;
  155.   xscl = width/21.0;
  156.   fn = dfont;
  157.   supsub = 0;
  158.   while (*chrs!='\0' && len>0) {
  159.     while (*chrs=='`') {
  160.       if (*(chrs+1)>='0' && *(chrs+1)<='9') {
  161.         fn = (int)*(chrs+1) - 48;
  162.         chrs+=2;
  163.         len-=2;
  164.       } else if (*(chrs+1)=='a') {
  165.         supsub = 1;
  166.         chrs+=2; len-=2;
  167.       } else if (*(chrs+1)=='b') {
  168.         supsub = 2;
  169.         chrs+=2; len-=2;
  170.       } else if (*(chrs+1)=='n') {
  171.         supsub = 0;
  172.         chrs+=2; len-=2;
  173.       } else break;
  174.     }
  175.     cdat = gxchgc ((int)*(chrs), fn, &ic);
  176.     if (cdat==NULL) return(1);
  177.     ic = (int)(*(cdat+3)) - 82;
  178.     jc = (int)(*(cdat+4)) - 82;
  179.     if (supsub) xs = xscl*0.45;
  180.     else xs = xscl;
  181.     *w = *w + (float)(jc-ic) * xs * 1.05;
  182.     chrs++; len--;
  183.   }
  184. }
  185.  
  186. /* Get location and length of particular character info
  187.    for particular font */
  188.  
  189. char * gxchgc (int ch, int fn, int *cnt) {
  190. int *clen, *coff, rc;
  191. char *fdat;
  192.  
  193.   if (fch[fn]==NULL) {
  194.     rc = gxchrd (fn);
  195.     if (rc) return(NULL);
  196.   }
  197.   clen = flen[fn];
  198.   coff = foff[fn];
  199.   fdat = fch[fn];
  200.   if (ch<32 || ch>127) ch=32;
  201.   ch = ch - 32;
  202.   *cnt = *(clen+ch);
  203.   return (fdat + *(coff+ch));
  204. }
  205.  
  206. /* Read in a font file */
  207.  
  208. int gxchrd (int fn) {
  209. FILE *ifile;
  210. char buff[20],*fname,*fdat;
  211. int i,j,rc,tlen,*coff,*clen,flag;
  212.  
  213.   sprintf (buff,"font%i.dat",fn);
  214.  
  215.   ifile = NULL;
  216.   fname = gxgnam(buff);
  217.   if (fname!=NULL) ifile = fopen(fname,"rb");
  218.   if (ifile==NULL) {
  219.     ifile = fopen(buff,"rb");
  220.     if (ifile==NULL) {
  221.       printf ("Error opening stroke character data set \n");
  222.       if (fname!=NULL) {
  223.         printf ("  Data set names = %s ; %s\n",fname,buff);
  224.         free (fname);
  225.       }
  226.       return(1);
  227.     }
  228.   }
  229.   free(fname);
  230.  
  231.   fseek (ifile,0L,2);
  232.   tlen = ftell(ifile);
  233.   fseek (ifile,0L,0);
  234.  
  235.   fdat = (char *)malloc(tlen+1);
  236.   if (fdat==NULL) {
  237.     printf ("Error reading font data:  Memory allocation error\n");
  238.     return(1);
  239.   }
  240.   coff = (int *)malloc(sizeof(int)*95);
  241.   if (coff==NULL) {
  242.     printf ("Error reading font data:  Memory allocation error\n");
  243.     free (fdat);
  244.     return(1);
  245.   }
  246.   clen = (int *)malloc(sizeof(int)*95);
  247.   if (clen==NULL) {
  248.     printf ("Error reading font data:  Memory allocation error\n");
  249.     free (fdat);
  250.     return(1);
  251.   }
  252.  
  253.   rc = fread(fdat,1,tlen,ifile);
  254.   if (rc!=tlen) {
  255.     printf ("Error reading font data: I/O Error\n");
  256.     return(1);
  257.   }
  258.   *(fdat+tlen) = '\0';
  259.  
  260.   /* Determine the locations of the start of each character */
  261.  
  262.   i = 0;
  263.   j = 1;
  264.   *(coff) = 0;
  265.   flag = 0;
  266.   while (*(fdat+i)) {
  267.     if (*(fdat+i)<' ') {
  268.       flag = 1;
  269.     } else {
  270.       if (flag) {
  271.         *(coff+j) = i;
  272.         j++;
  273.       }
  274.       flag = 0;
  275.     }
  276.     i++;
  277.   }
  278.  
  279.   /* Determine the count on each character */
  280.  
  281.   for (i=0; i<95; i++) {
  282.     for (j=0; j<3; j++) buff[j] = *(fdat+*(coff+i)+j);
  283.     buff[3] = '\0';
  284.     sscanf (buff,"%i",&rc);
  285.     *(clen+i) = rc;
  286.   }
  287.  
  288.   flen[fn] = clen;
  289.   foff[fn] = coff;
  290.   fch[fn] = fdat;
  291.  
  292.   return(0);
  293. }
  294.